home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / inetray / inetray.c < prev    next >
C/C++ Source or Header  |  1993-08-17  |  15KB  |  573 lines

  1. /*======================================================================
  2.                     I N E T R A Y . C 
  3.                     doc: Mon Feb 24 16:20:04 1992
  4.                     dlm: Tue Aug 17 13:51:54 1993
  5.                     (c) 1992 ant@julia
  6.                     uE-Info: 414 31 T 0 0 72 10 2 8 ofnI
  7. ======================================================================*/
  8.  
  9. /*#define        PRINTSCHEDULE        /* print scheduling info */
  10. /*#define        VERBOSE            /* print retrys */
  11.  
  12. #include    <stdio.h>        /* here we go! */
  13. #include    <signal.h>
  14. #include    <errno.h>
  15. #include    <fcntl.h>
  16. #include    <string.h>
  17. #include    <sys/types.h>
  18. #include    <sys/stat.h>
  19. #include    <sys/time.h>
  20. #include    <sys/param.h>
  21. #include    <rpc/rpc.h>
  22. #include    "inetray.h"
  23. #include    "config.h"
  24. #include    "common.h"
  25. #include    "comm.h"
  26. #include    "rayshade.h"
  27. #include    "options.h"
  28. #include    "picture.h"
  29. #include    "viewing.h"
  30. #include    "rcfile.h"
  31. #include    "lbuffer.h"
  32. #include    "version.h"
  33. #include    "patchlevel.h"
  34.  
  35. static Pixel    **line;            /* array for picture data */
  36. static int    bSize;            /* blocksize to trace in one sweep */
  37. static int    lSize;            /* size of last block in frame */
  38. static int    bNum;            /* number of blocks in frame */
  39. static char    *completed;        /* array for completed blocks */
  40. static int    doNext = 0;        /* next block to trace */
  41. static int    doNBlk = 2;        /* number of blocks to send */
  42. static char    pass2 = FALSE;        /* 2nd pass through picture */
  43. static int    reDo = 0;        /* reDo # of outstanding blocks */
  44. static int    nCompleted = 0;        /* number of lines completed per frame */
  45. static int    bCompleted = 0;        /* number of blocks completed per frame */
  46. static int    nSvc;            /* number of registered servers */
  47. static int    nextB2W;        /* next block to write to pic file */
  48. static int    bufPipe[2];        /* 2nd pipe to lBuffer */
  49. static int    tty;            /* read from keyboard */
  50.  
  51. int    key;                /* session key (exported) */
  52.  
  53. extern    int errno;            /* error number to restart syscalls */
  54.  
  55. main(ac,av)
  56. int ac; char *av[];
  57. {
  58.     static void initSelf(),initSubDiv(),initFrame();
  59.     static void printStats(),distAll(),sigCaught(),writeBlocks();
  60.     static int  initServers();
  61.     int    fd;
  62.     char    buf[64];
  63.     
  64.     if ((tty = open("/dev/tty",O_RDONLY)) < 0) {    /* keyboard */
  65.         perror("open(/dev/tty)");
  66.         exit(1);
  67.     }
  68.  
  69.     fprintf(stderr,"%s [%s%d]\n",av[0],VERSION,PATCHLEVEL);
  70.     initSelf(ac,av);            /* initialize self */
  71.     PictureStart(av);            /* open picture file */
  72.  
  73.     key = (int)time(NULL);            /* session key */
  74.     fprintf(stderr,"Session Key = %d\n",key);
  75.     rename(KEYFILE,OLDKEYFILE);        /* save keyfile */
  76.     fd = open(KEYFILE,O_CREAT|O_WRONLY,0600);
  77.     if (fd < 0) {
  78.         perror("open(KEYFILE)");
  79.     } else {
  80.         sprintf(buf,"%ld\n",key);    /* in ASCII */
  81.         if (write(fd,buf,strlen(buf)) < 0) {
  82.             perror("write");
  83.             exit(1);
  84.         }
  85.         close(fd);
  86.     }
  87.     
  88.     initServers(ac,av);            /* set up all servers */
  89.     initSubDiv();                /* init frame subdivision */
  90.  
  91.     for (Options.framenum=Options.startframe;
  92.          Options.framenum<=Options.endframe;
  93.           Options.framenum++) {
  94.         initFrame(Options.framenum);    /* init & send first requests */
  95.         if (Options.framenum>Options.startframe)
  96.             PictureStart(av);    /* write picture in parallel */
  97.         distAll();            /* distribute remaining lines */
  98.         writeBlocks(TRUE);        /* write remaining blocks */
  99.         fprintf(stderr,"Cleaning up... [kill");
  100.         killAll();            /* kill running workers */
  101.         fprintf(stderr,", flush");
  102.         flushAll();            /* discard pending input */
  103.         fprintf(stderr,", wait");
  104.         waitAll();            /* wait for workers to come down */
  105.         fprintf(stderr,"]");
  106.         PictureFrameEnd();        /* end picture frame */
  107.     }
  108.     PictureEnd();
  109.     Options.framenum = Options.endframe;    /* fix for stats */
  110.     printStats();
  111.     fprintf(stderr,"Exiting... [terminate"); 
  112.     terminateAll();                /* now exit everything */
  113.     fprintf(stderr,", close");
  114.     closeAll();
  115.     fprintf(stderr,"]\n");
  116.     exit(0);
  117. }
  118.  
  119. /*----------------------------------------------------------------------*/
  120. /*        initSelf and supporting routines            */
  121. /*----------------------------------------------------------------------*/
  122.  
  123. static void busError()                /* SUN4 weird bus errors */
  124. {
  125.     fprintf(stderr,"Warning: SIGBUS caught!\n");
  126. }
  127.  
  128. static void defSignals()            /* install default sigs */
  129. {
  130.     void    sigCaught();
  131.  
  132.     signal(SIGHUP,sigCaught);        /* all sigs which could mean */
  133.     signal(SIGINT,sigCaught);        /* terminate */
  134.     signal(SIGQUIT,sigCaught);
  135.     signal(SIGABRT,sigCaught);
  136.     signal(SIGTERM,sigCaught);
  137.     signal(SIGTSTP,sigCaught);
  138.     signal(SIGUSR1,sigCaught);
  139.     signal(SIGUSR2,sigCaught);
  140.     signal(SIGBUS,busError);        /* sometimes on SUN4s */
  141.     signal(SIGPIPE,shutDown);        /* ^C in pipeline */
  142. }
  143.  
  144. static void sigCaught()                /* abort signal rcved */
  145. {
  146.     char     ans;
  147.     
  148.     fprintf(stderr,"\nSignal received...\n");
  149.     if (getppid() != 1) {            /* parent alive */
  150.         fprintf(stderr,"Really abort <y/n>?");
  151.         do {                /* get ans from keyboard */
  152.             if (read(tty,&ans,1) != 1) {
  153.                 perror("read(tty)");
  154.                 exit(1);
  155.             }
  156.         }
  157.         while ((ans != 'y') && (ans != 'Y') &&
  158.                (ans != 'n') && (ans != 'N'));
  159.         if ((ans == 'y') || (ans == 'Y')) shutDown(0);
  160.     } else shutDown(0);
  161.     defSignals();
  162. }
  163.     
  164.  
  165. static void initFrame(f)            /* init frame */
  166. int f;
  167. {
  168.     int     i;
  169.     void     dist1st();
  170.     
  171.     for (i=0; i<bNum; i++)             /* clear completed flags */
  172.         completed[i] = FALSE;
  173.     doNext = nCompleted = 0;        /* reset counters */
  174.     pass2 = FALSE;
  175.     reDo = nextB2W = bCompleted = 0;
  176.     fprintf(stderr,"\nFrame #%d:\n",f); 
  177.     dist1st(f);                /* begin trace */
  178. }
  179.  
  180. static void initSelf(ac,av)            /* init stuff */
  181. int ac; char *av[];
  182. {
  183.     int bPid,i,lnSize,saveIn,p[2];
  184.  
  185.     readRc();                /* read .rc-file */
  186.     
  187.     if (pipe(p) < 0) {            /* set up input */
  188.         perror("pipe");
  189.         exit(1);
  190.     }
  191.  
  192.     if (pipe(bufPipe) < 0) {        /* 2nd lBuffer pipe */
  193.         perror("pipe");
  194.         exit(1);
  195.     }
  196.     bPid = lPreBuffer(p,bufPipe);
  197.  
  198.     saveIn = dup(IN);            /* redirect stdin */
  199.     close(IN);
  200.     dup(p[IN]);
  201.     close(p[IN]);
  202.  
  203.     RSInitialize(ac,av);            /* options, file, ... */
  204.     kill(bPid,SIGUSR1);            /* kill if still killable */
  205.  
  206.     close(IN);                /* reset stdin */
  207.     dup(saveIn);
  208.     
  209.     wait(NULL);                /* from popen() */
  210.     defSignals();                /* signals */
  211.  
  212.     line = (Pixel **)malloc(Screen.ysize * sizeof(Pixel *));
  213.     if (line == NULL) {
  214.         fprintf(stderr,"malloc() failed\n");
  215.         exit(1);
  216.     }
  217.     lnSize = Screen.xsize * sizeof(Pixel);
  218.     for (i=0; i<Screen.ysize; i++) {
  219.         line[i] = (Pixel *)malloc(lnSize);
  220.         if (line[i] == NULL) {
  221.             perror("malloc");
  222.             exit(1);
  223.         }
  224.     }
  225. }
  226.  
  227. static void initSubDiv()            /* init frame subdivision */
  228. {
  229.     bSize = Screen.ysize / nSvc
  230.             / blocksPerServer;    /* estimated size of blocks */
  231.     if (bSize < minBlockSize)        /* assert bounds */
  232.         bSize = minBlockSize;
  233.     if (bSize > maxBlockSize)
  234.         bSize = maxBlockSize;
  235.     bNum = Screen.ysize / bSize + 1;    /* number of blocks */
  236.     lSize = Screen.ysize-(bNum-1)*bSize;    /* remaining lines */
  237.     if (lSize == 0) {            /* no remaining lines */
  238.         bNum--;
  239.         lSize = bSize;
  240.     }
  241.  
  242.     completed = (char *)malloc(bNum);    /* supporting structures */
  243.     if (completed == NULL) {
  244.         fprintf(stderr,"malloc() failed\n");
  245.         exit(1);
  246.     }
  247.     fprintf(stderr,"Frame Subdivision:");
  248.     fprintf(stderr,"\n\t%d Blocks per Frame",bNum);
  249.     fprintf(stderr,"\n\t%d Lines per Block",bSize);
  250.     if (lSize != bSize)
  251.         fprintf(stderr,"\n\t%d Lines in Last Block",lSize);
  252. }
  253.     
  254.  
  255. /*----------------------------------------------------------------------*/
  256. /*        distribution                         */
  257. /*----------------------------------------------------------------------*/
  258.  
  259. static int findNext()                /* next blockNr */
  260. {
  261.     int i,sm= -1,nx= -1,next;
  262.  
  263.     for (i=0; i<bNum; i++)
  264.         if (!completed[i]) {
  265.             if (sm < 0) sm = i;
  266.             if ((nx < 0) && (i >= doNext)) nx = i;
  267.         }
  268.     if (sm < 0) return FALSE;
  269.     
  270.     if (nx < 0) {                /* original next */
  271.         if (!pass2) {
  272.             fprintf(stderr,"\tEnd of Pass #1\n");
  273.             pass2 = TRUE;
  274.         }
  275.         next = sm;
  276.     } else next = nx;
  277.     
  278.     if (reDo > 0) {                /* rescheduled */
  279.         reDo--;
  280.         doNext = sm;
  281.         doNBlk = 1;
  282.     } else if (pass2 || next == bNum-1 || next == bNum-2) {
  283.         doNext = next;
  284.         doNBlk = 1;
  285.     } else {
  286.         doNext = next;
  287.         doNBlk = 2;
  288.     }
  289.     return TRUE;
  290. }
  291.  
  292. static void dist1st(frame)            /* dist 1 block p. server */
  293. int frame;
  294. {
  295.     hInfo    *host;
  296.     int     res,rpcerr,nTrys;
  297.     sfPrm    paramSF;
  298.     
  299.     for (host = hosts; host != NULL; host = host->next) {
  300.         if (!findNext()) return;
  301.         host->fDone = 0;
  302.         if (host->broken) continue;
  303.         paramSF.key = key;
  304.         paramSF.fNr = frame;
  305.         for (nTrys = 10; nTrys > 0; nTrys--) {
  306.             rpcerr = clnt_call(host->clnt,STARTFRAME,
  307.                          xdr_sfPrm,¶mSF,
  308.                        xdr_int,&res,callTOut);
  309.             if (rpcerr == RPC_SUCCESS) break;
  310.             if (rpcerr == RPC_TIMEDOUT) {
  311. #ifdef VERBOSE
  312.                 fprintf(stderr,"STARTFRAME retry to %s\n",host->name);
  313. #endif
  314.                 host->reTrys++;
  315.                 if (nTrys > 1) continue;
  316.             }
  317.             fprintf(stderr,"startframe(): ");
  318.             abort1(host);
  319.         }
  320.         host->request.key = key;
  321.         host->request.bNr = doNext;
  322.         host->request.bSz = (doNext == bNum-1) ? lSize : bSize;
  323.         host->request.lNr = doNext*bSize;
  324.         host->request.nBlocks = doNBlk;
  325.         clnt_call(host->clnt,TRACEBLOCK,
  326.                 xdr_tbPrm,&(host->request),
  327.                 xdr_void,NULL,now);
  328. #ifdef PRINTSCHEDULE
  329.         fprintf(stderr,"\tBlock(s) #%d-#%d sent to %s(%d)\n",
  330.                 doNext,doNext+doNBlk-1,host->name,host->wid);
  331. #endif
  332.         doNext += doNBlk;
  333.     }
  334. }
  335.         
  336. static void printStats()            /* print statistics */
  337. {
  338.     hInfo    *host,*bHost;
  339.     int    tot,all,best;
  340.     char    nBuf[MAXHOSTNAMELEN+10];
  341.  
  342.     if (getppid() == 1) shutDown(0);
  343.     signal(SIGINT,sigCaught); 
  344.     fprintf(stderr,"\nStatistics:\n"); 
  345.     tot = (Options.framenum-Options.startframe)*Screen.ysize+nCompleted;
  346.     if (tot == 0) tot = 1;
  347.     for (all=0; all<nSvc; all++) {
  348.         best = 0;
  349.         for (host = hosts; host != NULL; host = host->next) 
  350.                 if (host->done >= best) {
  351.                     best = host->done;
  352.                     bHost = host;
  353.                 }
  354.         if (bHost->done == 0) bHost->done = -1;
  355.         else bHost->done = -bHost->done;
  356.         putc('\t',stderr);
  357.         sprintf(nBuf,"%s[%d]",bHost->name,bHost->pid);
  358.         fprintf(stderr,"\t%-15.14s",nBuf);
  359.         if (bHost->broken) fprintf(stderr,"# ");
  360.         else fprintf(stderr,"  ");
  361.         if (bHost->reTrys != 0)
  362.             fprintf(stderr,"%4d",bHost->reTrys);
  363.         fprintf(stderr,"\t");
  364.         fprintf(stderr,"%d \t(%d%%)\n",best,100*best/tot);
  365.     }
  366.     for (host = hosts; host != NULL; host = host->next)
  367.         if (host->done == -1) host->done = 0;
  368.         else host->done = -host->done;
  369.     if (getppid() == 1) shutDown(0);
  370. }
  371.  
  372. static void writeBlocks(flush)
  373. char flush;
  374. {
  375.     int     i,bSz,writ = 0;            /* write to file */
  376.     hInfo     *h;
  377.     fd_set    sockSet;
  378.     
  379.     while ((nextB2W < bNum) && completed[nextB2W]) {
  380.         if (writ == 0)
  381.             fprintf(stderr,"\tWriting... ");
  382.         bSz = (nextB2W == bNum-1) ? lSize : bSize;
  383.         for (i=0; i<bSz; i++)
  384.             PictureWriteLine(line[nextB2W*bSize+i]);
  385.         nextB2W++; writ++;
  386.         if (!flush) {            /* check for input */
  387.                 FD_ZERO(&sockSet);
  388.             for (h = hosts; h != NULL; h = h->next)
  389.                 if (!h->broken)
  390.                     FD_SET(h->sock,&sockSet);
  391.                 if (select(sfdmax+1,&sockSet,
  392.                     (fd_set *)NULL,(fd_set *)NULL,
  393.                     &now) != 0) {
  394.                 fprintf(stderr,"[interrupted] ");
  395.                 break;
  396.             }
  397.         }
  398.     }
  399.     if (writ == 1)                /* report it */
  400.         fprintf(stderr,"(1 block)\n");
  401.     else if (writ > 1)
  402.         fprintf(stderr,"(%d blocks)\n",writ);
  403. }
  404.  
  405. static char getBlock(host)            /* get traced block */
  406. hInfo *host;
  407. {
  408.     pixArr    xdrline;
  409.     int    bNr,bSz,i;            /* block info */
  410.     XDR     *xdrs;
  411.     hInfo    *h;
  412.     
  413.     xdrs = &(host->xdrs);
  414.       if (!xdrrec_skiprecord(xdrs)) {     /* read next record*/
  415.           fprintf(stderr,"xdrrec_skiprecord(): ");
  416.           abort1(host);
  417.         return FALSE;
  418.     }
  419.     if (!xdr_int(xdrs,&bNr)) {        /* get block number */
  420.         abort1(host);
  421.         return FALSE;
  422.     }
  423.  
  424.     bSz = (bNr == bNum-1) ? lSize : bSize;    /* calc block size */
  425.  
  426.     for (i=0; i<bSz; i++) {            /* read all lines */
  427.             xdrline.pixArr_val = (xdrPix *)line[bNr*bSize+i];
  428.             if (!xdr_pixArr(xdrs,&xdrline)) {
  429.                     fprintf(stderr,"xdr_pixArr(): ");
  430.             abort1(host);
  431.             return FALSE;
  432.         }
  433.     }
  434.     host->request.nBlocks--;
  435. #ifdef PRINTSCHEDULE
  436.     fprintf(stderr,"\tBlock #%d received from %s(%d)\n",
  437.             bNr,host->name,host->wid);
  438.     fprintf(stderr,"\t%d Block(s) remaining\n",
  439.             host->request.nBlocks);
  440. #endif
  441.     if (!completed[bNr]) {            /* reporting & statistics */
  442.         completed[bNr] = TRUE;
  443.         if (nCompleted/Options.report_freq <
  444.             (nCompleted+bSz)/Options.report_freq) {
  445.             fprintf(stderr,"\tFinished line %d\n",nCompleted+bSz);
  446.         }
  447.         nCompleted += bSz;        /* update stats */
  448.         bCompleted++;
  449.         host->done += bSz;
  450.         host->fDone += bSz;
  451. /*        if (bCompleted == bNum/2) {
  452.             for (h = hosts; h != NULL; h = h->next)
  453.                 if (h->fDone == 0) reDo++;
  454.             if (reDo > bNum/4) reDo = 0;
  455.             reDo *= 2;
  456.             if (reDo == 1)
  457.                 fprintf(stderr,"\t1 block rescheduled\n");
  458.             else
  459.                 fprintf(stderr,"\t%d blocks rescheduled\n",reDo);
  460.         } */
  461.     }
  462.     writeBlocks(FALSE);    
  463.     return TRUE;
  464. }
  465.  
  466.     
  467. static void distAll()                /* block distribution routine */
  468. {
  469.     fd_set    sockSet;
  470.     int        res;
  471.     hInfo    *host;
  472.     char    timedOut;
  473.  
  474.     do {                    /* loop on all blocks */
  475.     signal(SIGINT,printStats);
  476.     
  477.     restartSelect:
  478.         FD_ZERO(&sockSet);            /* select() on sockets */
  479.     for (host = hosts; host != NULL; host = host->next)
  480.         if (!host->broken)
  481.             FD_SET(host->sock,&sockSet);
  482.     timedOut = TRUE;
  483.         res = select(sfdmax+1,&sockSet,
  484.             (fd_set *)NULL,(fd_set *)NULL,
  485.             &resend);
  486.         if (res < 0) {
  487.             if (errno == EINTR) goto restartSelect;
  488.                 perror("select");
  489.         exit(1);
  490.     }
  491.     
  492.     for (host = hosts; host != NULL; host = host->next) {
  493.             if (!FD_ISSET(host->sock,&sockSet)) continue;
  494.             if (host->broken) continue;
  495.             timedOut = FALSE;
  496.             if (!getBlock(host))        /* read one result */
  497.             continue;        /* connection broken */
  498.         if (host->request.nBlocks > 0)    /* not done yet */
  499.             continue;
  500.         if (!findNext()) return;    /* next line to trace */
  501.         host->request.key = key;        /* next block */
  502.         host->request.bNr = doNext;
  503.         host->request.bSz = (doNext == bNum-1) ? lSize : bSize;
  504.         host->request.lNr = doNext * bSize;
  505.         host->request.nBlocks = doNBlk;
  506.         (void)clnt_call(host->clnt,TRACEBLOCK,
  507.                 xdr_tbPrm,&(host->request),
  508.                 xdr_void,NULL,
  509.                 now);
  510. #ifdef PRINTSCHEDULE
  511.         fprintf(stderr,"\tBlock(s) #%d-#%d sent to %s(%d)\n",
  512.                 doNext,doNext+doNBlk-1,host->name,host->wid);
  513. #endif
  514.         doNext += doNBlk;
  515.     }
  516.  
  517.     } FOREVER;                    
  518. }
  519.  
  520. /*----------------------------------------------------------------------*/
  521. /*        initClients()                        */
  522. /*----------------------------------------------------------------------*/
  523.  
  524. static char *makePStr(ac,av)            /* build param-str */
  525. int ac; char *av[];
  526. {
  527.     int abp,ap,i;
  528.     static char argbuf[256];
  529.  
  530.     for (abp=0,ap=0; ap < ac; ap++) {
  531.         argbuf[abp++] = '\'';
  532.         for (i=0; av[ap][i] != '\0'; i++)
  533.             argbuf[abp++] = av[ap][i];
  534.         argbuf[abp++] = '\'';
  535.         argbuf[abp++] = ' ';
  536.     }
  537.     argbuf[abp] = '\0';
  538.     return argbuf;
  539. }
  540.  
  541. static int initServers(ac,av)            /* init all servers */
  542. int ac; char *av[];
  543. {
  544.     char    cwd[MAXPATHLEN],hname[MAXHOSTNAMELEN];
  545.     char    *getcwd();
  546.     struct stat sBuf;
  547.  
  548.     if (gethostname(hname,MAXHOSTNAMELEN) < 0) {
  549.         perror("gethostname");
  550.         exit(1);
  551.     }
  552.     if (fstat(bufPipe[IN],&sBuf) < 0) {    /* buffer alive? */
  553.         perror("fstat");
  554.         exit(1);
  555.     }
  556.     fprintf(stderr,"Registering... ["); 
  557.     registerSvc(hname,makePStr(ac,av),
  558.             getcwd(cwd,MAXPATHLEN),sBuf.st_size>0);
  559.     nSvc = nRunning;
  560.     if (nSvc == 0) {
  561.         fprintf(stderr,"\nError: no Inetray Servers answering!\n");
  562.         exit(1);
  563.     }
  564.     fprintf(stderr,"\n[%d workers registered]\n",nSvc);
  565.  
  566.     if (sBuf.st_size>0) {            /* send file */
  567.         fprintf(stderr,"Distibuting StdIn...");
  568.         distribute(bufPipe[IN]);
  569.         fprintf(stderr,"\n");
  570.     }
  571.     wait(NULL);                /* wait for buffer */
  572. }
  573.